package com.cykj.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.cykj.order.domain.BsOrders;
import com.cykj.order.domain.BsRegion;
import com.cykj.order.domain.vo.BsOrdersVo;
import com.cykj.order.service.OrderCacheService;
import com.cykj.order.util.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 订单缓存服务实现类
 * 
 * @author cykj
 * @date 2025-08-20
 */
@Service
public class OrderCacheServiceImpl implements OrderCacheService {
    
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    
    // 缓存过期时间常量
    private static final long ORDER_STATUS_EXPIRE_MINUTES = 30; // 订单状态缓存30分钟
    private static final long ORDER_INFO_EXPIRE_MINUTES = 15;   // 订单详情缓存15分钟
    private static final long ORDER_LIST_EXPIRE_MINUTES = 10;   // 订单列表缓存10分钟
    private static final long REGION_TREE_EXPIRE_HOURS = 2;     // 地区树缓存2小时
    private static final long ORDER_COUNT_EXPIRE_HOURS = 1;     // 订单统计缓存1小时
    
    @Override
    public void cacheOrderStatus(Long orderId, Integer status) {
        if (orderId == null || status == null) {
            return;
        }
        
        String key = RedisKeyUtil.getOrderStatusKey(orderId);
        stringRedisTemplate.opsForValue().set(key, status.toString(), ORDER_STATUS_EXPIRE_MINUTES, TimeUnit.MINUTES);
    }
    
    @Override
    public Integer getCachedOrderStatus(Long orderId) {
        if (orderId == null) {
            return null;
        }
        
        String key = RedisKeyUtil.getOrderStatusKey(orderId);
        String statusStr = stringRedisTemplate.opsForValue().get(key);
        
        if (statusStr != null && !statusStr.isEmpty()) {
            try {
                return Integer.valueOf(statusStr);
            } catch (NumberFormatException e) {
                // 删除无效缓存
                removeOrderStatusCache(orderId);
            }
        }
        return null;
    }
    
    @Override
    public void removeOrderStatusCache(Long orderId) {
        if (orderId == null) {
            return;
        }
        
        String key = RedisKeyUtil.getOrderStatusKey(orderId);
        stringRedisTemplate.delete(key);
    }
    
    @Override
    public void cacheOrderInfo(BsOrdersVo orderVo) {
        if (orderVo == null || orderVo.getId() == null) {
            return;
        }
        
        String key = RedisKeyUtil.getOrderInfoKey(orderVo.getId());
        String jsonStr = JSON.toJSONString(orderVo);
        stringRedisTemplate.opsForValue().set(key, jsonStr, ORDER_INFO_EXPIRE_MINUTES, TimeUnit.MINUTES);
    }
    
    @Override
    public BsOrdersVo getCachedOrderInfo(Long orderId) {
        if (orderId == null) {
            return null;
        }
        
        String key = RedisKeyUtil.getOrderInfoKey(orderId);
        String jsonStr = stringRedisTemplate.opsForValue().get(key);
        
        if (jsonStr != null && !jsonStr.isEmpty()) {
            try {
                return JSON.parseObject(jsonStr, BsOrdersVo.class);
            } catch (Exception e) {
                // 删除无效缓存
                removeOrderInfoCache(orderId);
            }
        }
        return null;
    }
    
    @Override
    public void removeOrderInfoCache(Long orderId) {
        if (orderId == null) {
            return;
        }
        
        String key = RedisKeyUtil.getOrderInfoKey(orderId);
        stringRedisTemplate.delete(key);
    }
    
    @Override
    public void cacheRegionTree(List<BsRegion> regionTree) {
        if (regionTree == null) {
            return;
        }
        
        String key = RedisKeyUtil.getRegionTreeKey();
        String jsonStr = JSON.toJSONString(regionTree);
        stringRedisTemplate.opsForValue().set(key, jsonStr, REGION_TREE_EXPIRE_HOURS, TimeUnit.HOURS);
    }
    
    @Override
    public List<BsRegion> getCachedRegionTree() {
        String key = RedisKeyUtil.getRegionTreeKey();
        String jsonStr = stringRedisTemplate.opsForValue().get(key);
        
        if (jsonStr != null && !jsonStr.isEmpty()) {
            try {
                return JSON.parseObject(jsonStr, new TypeReference<List<BsRegion>>() {});
            } catch (Exception e) {
                // 删除无效缓存
                removeRegionTreeCache();
            }
        }
        return null;
    }
    
    @Override
    public void removeRegionTreeCache() {
        String key = RedisKeyUtil.getRegionTreeKey();
        stringRedisTemplate.delete(key);
    }
    
    @Override
    public void incrementOrderStatusCount(Long shopId, Integer status) {
        if (shopId == null || status == null) {
            return;
        }
        
        String key = RedisKeyUtil.getOrderStatusCountKey(shopId, status);
        stringRedisTemplate.opsForValue().increment(key);
        // 设置过期时间
        stringRedisTemplate.expire(key, ORDER_COUNT_EXPIRE_HOURS, TimeUnit.HOURS);
    }
    
    @Override
    public void decrementOrderStatusCount(Long shopId, Integer status) {
        if (shopId == null || status == null) {
            return;
        }
        
        String key = RedisKeyUtil.getOrderStatusCountKey(shopId, status);
        Long count = stringRedisTemplate.opsForValue().decrement(key);
        
        // 如果计数为0或负数，删除key
        if (count != null && count <= 0) {
            stringRedisTemplate.delete(key);
        } else {
            // 重新设置过期时间
            stringRedisTemplate.expire(key, ORDER_COUNT_EXPIRE_HOURS, TimeUnit.HOURS);
        }
    }
    
    @Override
    public Long getOrderStatusCount(Long shopId, Integer status) {
        if (shopId == null || status == null) {
            return 0L;
        }
        
        String key = RedisKeyUtil.getOrderStatusCountKey(shopId, status);
        String countStr = stringRedisTemplate.opsForValue().get(key);
        
        if (countStr != null && !countStr.isEmpty()) {
            try {
                return Long.valueOf(countStr);
            } catch (NumberFormatException e) {
                return 0L;
            }
        }
        return 0L;
    }
    
    @Override
    public void cacheOrderList(BsOrders queryParams, List<BsOrdersVo> orderList) {
        if (queryParams == null || orderList == null) {
            return;
        }
        
        try {
            // 生成查询参数的哈希值作为缓存键
            String queryHash = generateQueryHash(queryParams);
            String key = RedisKeyUtil.getOrderListKey(queryHash);
            String value = JSON.toJSONString(orderList);
            
            stringRedisTemplate.opsForValue().set(key, value, ORDER_LIST_EXPIRE_MINUTES, TimeUnit.MINUTES);
        } catch (Exception e) {
            // 缓存失败不影响业务流程，只记录日志
            System.err.println("缓存订单列表失败: " + e.getMessage());
        }
    }
    
    @Override
    public List<BsOrdersVo> getCachedOrderList(BsOrders queryParams) {
        if (queryParams == null) {
            return null;
        }
        
        try {
            String queryHash = generateQueryHash(queryParams);
            String key = RedisKeyUtil.getOrderListKey(queryHash);
            String value = stringRedisTemplate.opsForValue().get(key);
            
            if (value != null && !value.isEmpty()) {
                return JSON.parseObject(value, new TypeReference<List<BsOrdersVo>>() {});
            }
        } catch (Exception e) {
            System.err.println("获取缓存订单列表失败: " + e.getMessage());
        }
        
        return null;
    }
    
    @Override
    public void clearOrderListCache() {
        try {
            // 使用Lua脚本删除匹配的键，避免大量网络IO
            String script = 
                "local keys = redis.call('keys', ARGV[1]) " +
                "if #keys > 0 then " +
                "    return redis.call('del', unpack(keys)) " +
                "else " +
                "    return 0 " +
                "end";
            
            stringRedisTemplate.execute(
                (org.springframework.data.redis.core.script.RedisScript<Long>) 
                org.springframework.data.redis.core.script.RedisScript.of(script, Long.class),
                java.util.Collections.emptyList(),
                RedisKeyUtil.getOrderListKeyPrefix()
            );
        } catch (Exception e) {
            System.err.println("清理订单列表缓存失败: " + e.getMessage());
        }
    }
    
    /**
     * 生成查询参数的哈希值
     * 
     * @param queryParams 查询参数
     * @return 哈希值字符串
     */
    private String generateQueryHash(BsOrders queryParams) {
        StringBuilder sb = new StringBuilder();
        
        if (queryParams.getOrderNumber() != null) {
            sb.append("orderNumber:").append(queryParams.getOrderNumber()).append("|");
        }
        if (queryParams.getUserId() != null) {
            sb.append("userId:").append(queryParams.getUserId()).append("|");
        }
        if (queryParams.getShopId() != null) {
            sb.append("shopId:").append(queryParams.getShopId()).append("|");
        }
        if (queryParams.getStatus() != null) {
            sb.append("status:").append(queryParams.getStatus()).append("|");
        }
        if (queryParams.getPaymentMethod() != null) {
            sb.append("paymentMethod:").append(queryParams.getPaymentMethod()).append("|");
        }
        if (queryParams.getBeginTime() != null) {
            sb.append("beginTime:").append(queryParams.getBeginTime()).append("|");
        }
        if (queryParams.getEndTime() != null) {
            sb.append("endTime:").append(queryParams.getEndTime()).append("|");
        }
        // 添加缺失的搜索条件
        if (queryParams.getUserPhone() != null) {
            sb.append("userPhone:").append(queryParams.getUserPhone()).append("|");
        }
        if (queryParams.getUserName() != null) {
            sb.append("userName:").append(queryParams.getUserName()).append("|");
        }
        if (queryParams.getShopName() != null) {
            sb.append("shopName:").append(queryParams.getShopName()).append("|");
        }
        
        // 生成简单的哈希值
        return String.valueOf(sb.toString().hashCode());
    }
}
